package com.huamao.zh.service.impl;

import static com.huamao.zh.base.DateUtils.DateToString_YYYYMMDD;
import static com.huamao.zh.base.DateUtils.getYesterday;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.huamao.zh.base.SerialNumberUtils;
import com.huamao.zh.constants.KaiyuanType;
import com.huamao.zh.constants.LogCodeType;
import com.huamao.zh.constants.ScoreType;
import com.huamao.zh.model.Account;
import com.huamao.zh.model.AgentsAccount;
import com.huamao.zh.model.CheckAccountTmp;
import com.huamao.zh.model.DateTransform;
import com.huamao.zh.service.AccountService;
import com.huamao.zh.service.AgentsAccountService;
import com.huamao.zh.service.CheckAccountTmpService;
import com.huamao.zh.service.DateTransformService;
import com.huamao.zh.service.LogErrorService;
import com.huamao.zh.service.LogKaiyuanAgentService;
import com.huamao.zh.service.LogKaiyuanService;
import com.huamao.zh.service.LogScoreAgentService;
import com.huamao.zh.service.LogScoreService;
import com.huamao.zh.service.ScoreToKaiyuanService;

/**
 * 积分转换华宝 Created by Bourne on 2017-11-16.
 */
@Service
public class ScoreToKaiyuanImpl implements ScoreToKaiyuanService {

	@Autowired
	private AccountService accountService;
	@Autowired
	CheckAccountTmpService checkAccountTmpService;
	@Autowired
	private LogScoreService logScoreService;
	@Autowired
	private LogKaiyuanService logKaiyuanService;
	@Autowired
	private DateTransformService dateTransformService;
	@Autowired
	private AgentsAccountService agentsAccountService;
	@Autowired
	private LogScoreAgentService logScoreAgentService;
	@Autowired
	private LogKaiyuanAgentService logKaiyuanAgentService;
	@Autowired
	private LogErrorService logErrorService;
	// @Autowired
	// private RedisSentinelManager redisSentinelManager;

	/**
	 * 积分总量
	 */
	private BigDecimal totalScore = BigDecimal.valueOf(0);
	/**
	 * 转换的积分总量
	 */
	private BigDecimal totalCutScore = BigDecimal.valueOf(0);
	/**
	 * 转换的总人次
	 */
	private Integer totalUsers = 0;
	private int yesterday;
	private int ratioId = 0;
	/**
	 * 转换比例（万分之几）
	 */
	private BigDecimal ratio = BigDecimal.valueOf(6.001);
	/**
	 * 1万为一个转换单位
	 */
	private BigDecimal beishu = BigDecimal.valueOf(10000);
	private LogCodeType logCodeType;
	/**
	 * 每次处理人数
	 */
	private Integer perNum = 10000;

	@Override
	public void scoreToKaiyuan() throws Exception {
		yesterday = Integer.parseInt(DateToString_YYYYMMDD(getYesterday()));
		// long res = redisSentinelManager.incr("scoreToKaiyuan_" + yesterday);
		logCodeType = LogCodeType.CODE_2001;
		// LogUtil.info(logCodeType, yesterday +
		// "==开始执行====scoreToKaiyuan========" + res);
		// if (res > 1) {
		// LogUtil.info(LogCodeType.CODE_1000, "重复执行了");
		// return;
		// }
		this.scoreToKaiyuan(1);
		logCodeType = LogCodeType.CODE_2002;
		this.scoreToKaiyuan(2);
		// redisSentinelManager.del("scoreToKaiyuan_" + yesterday);
	}

	/**
	 * 消费者积分转换华宝
	 *
	 * @param type
	 *            1是消费者 2是代理公司
	 */
	private void scoreToKaiyuan(Integer type) {
		totalScore = BigDecimal.valueOf(0);
		totalCutScore = BigDecimal.valueOf(0);
		totalUsers = 0;
		boolean getRatio = getRatio(type);
		// 不符合执行条件
		if (!getRatio) {
			return;
		}
		// LogUtil.info(logCodeType, yesterday + "==select all====" + type);
		Map<String, Object> option = new HashMap<>();
		int start = 0;
		Date date = new Date();
		boolean nextTask = true;
		while (nextTask) {
			Integer listSize;// 本次循环执行总数量
			// LogUtil.info(logCodeType, yesterday + "==循环起点=====" + start);
			option.put("score", beishu);
			option.put("start", start);
			option.put("num", perNum);
			if (type == 1) {
				listSize = addUserKaiyuan(option, ratio);
			} else {
				listSize = addAgentKaiyuan(option, ratio);
			}
			start += perNum;
			if (listSize < perNum) {
				nextTask = false;
			}
		}
		// LogUtil.info(logCodeType, yesterday + "==" + type + "循环结束=====总人数:" +
		// totalUsers + ",积分总量:" + totalScore
		// + "(万),减少积分" + totalCutScore);
		try {
			if (ratioId > 0) {
				dateTransformService.updateSelective(ratioId, totalScore, totalCutScore, totalUsers, date);
			} else {
				dateTransformService.addSelective(type, yesterday, ratio, totalScore, totalCutScore, totalUsers, date);
			}
			return;
		} catch (Exception e) {
			try {
				logErrorService.add("ScoreToKaiyuan", -type,
						"总人数:" + totalUsers + ",积分总量:" + totalScore + "(万),减少积分:" + totalCutScore, e.toString());
			} catch (Exception e1) {

			}
			// LogUtil.info(logCodeType, "记载汇总出错=====" + e);
		}
	}

	/**
	 * 获取转换比例
	 *
	 * @param type
	 * @return
	 */
	private boolean getRatio(Integer type) {
		List<DateTransform> ratioList = dateTransformService.getRatio(type);
		if (ratioList.size() > 0) {
			ratioId = ratioList.get(0).getId();
			int ratioDate = ratioList.get(0).getDate();
			// LogUtil.info(logCodeType, "最近配置比例日期:" + ratioDate + ",应转换日期:" +
			// yesterday);
			// 取得最近配置的转换比例
			ratio = ratioList.get(0).getRatio();
			if (yesterday > ratioDate) {
				// 表示最近的配置不是昨天的
				ratioId = -1;
			} else if (yesterday == ratioDate && ratioList.get(0).getUserNum() > -1) {
				// 表示昨天的已经执行过
				return false;
			}
		}
		if (ratio.compareTo(BigDecimal.valueOf(10000)) == 1) {
			return false;
		}
		return true;
	}

	/**
	 * 消费者
	 *
	 * @param option
	 * @param ratio
	 * @return 本次执行人数
	 */
	@Transactional
	Integer addUserKaiyuan(Map<String, Object> option, BigDecimal ratio) {
		List<CheckAccountTmp> list = checkAccountTmpService.queryScoreList(option);
		for (CheckAccountTmp account : list) {
			int accountId = account.getAccountId();
			int userId = account.getUserId();
			BigDecimal score = account.getScoreToday();
			// 参与计算的积分
			score = score.divideAndRemainder(beishu)[0];
			// 减少积分，获得的华宝
			BigDecimal getKaiyuan = score.multiply(ratio);
			try {
				String orderNo = SerialNumberUtils.generateOrderNo("");
				Account updateAcc = new Account();
				updateAcc.setAccountId(accountId);
				updateAcc.setScore(getKaiyuan);
				// 更新账户
				accountService.scoreToKaiyuan(updateAcc);
				// 记录积分流水
				logScoreService.add(ScoreType.Turn_2_kaiyuan.getCode(), 0, userId, orderNo, account.getScoreToday(), -1,
						getKaiyuan, ScoreType.Turn_2_kaiyuan.getName());
				// 记录华宝流水
				logKaiyuanService.add(KaiyuanType.Transfer_in.getCode(), 0, userId, orderNo, 0,
						account.getKaiyuanToday(), 1, getKaiyuan, KaiyuanType.Transfer_in.getName());
				// LogUtil.info(logCodeType, "用户id:" + userId + ",原积分:" + score
				// + "(万),减少积分:" + getKaiyuan);
				totalScore = totalScore.add(score);
				totalCutScore = totalCutScore.add(getKaiyuan);
				totalUsers++;
			} catch (Exception e) {
				try {
					logErrorService.add("userScoreToKaiyuan", userId,
							"积分总量:" + account.getScoreToday() + "(万),减少积分:" + getKaiyuan, e.toString());
				} catch (Exception e1) {

				}
				// LogUtil.info(logCodeType, "出错了,用户id:" + userId + "=======" +
				// e);
			}
		}
		return list.size();
	}

	/**
	 * 代理公司
	 *
	 * @param option
	 * @param ratio
	 * @return 本次执行人数
	 */
	@Transactional
	Integer addAgentKaiyuan(Map<String, Object> option, BigDecimal ratio) {
		List<AgentsAccount> list = agentsAccountService.queryScoreList(option);

		for (AgentsAccount account : list) {
			int accountId = account.getAccountId();
			int agentId = account.getAgentId();
			BigDecimal score = account.getScore();
			// 参与计算的积分
			score = score.divideAndRemainder(beishu)[0];
			BigDecimal getKaiyuan = score.multiply(ratio);

			try {
				String orderNo = SerialNumberUtils.generateOrderNo("");
				AgentsAccount updateAcc = new AgentsAccount();
				updateAcc.setAccountId(accountId);
				updateAcc.setScore(getKaiyuan);
				// 更新账户
				agentsAccountService.scoreToKaiyuan(updateAcc);
				// 记录积分流水
				logScoreAgentService.add(ScoreType.Turn_2_kaiyuan.getCode(), 0, agentId, orderNo, account.getScore(),
						-1, getKaiyuan, ScoreType.Turn_2_kaiyuan.getName());
				// 记录华宝流水
				logKaiyuanAgentService.add(KaiyuanType.Transfer_in.getCode(), 0, agentId, orderNo, 0,
						account.getKaiyuan(), 1, getKaiyuan, KaiyuanType.Transfer_in.getName());
				// LogUtil.info(logCodeType, "代理公司id:" + agentId + ",原积分:" +
				// score + "(万),减少积分:" + getKaiyuan);
				totalScore = totalScore.add(score);
				totalCutScore = totalCutScore.add(getKaiyuan);
				totalUsers++;
			} catch (Exception e) {
				try {
					logErrorService.add("agentScoreToKaiyuan", agentId,
							"积分总量:" + account.getScore() + "(万),减少积分:" + getKaiyuan, e.toString());
				} catch (Exception e1) {

				}
				// LogUtil.info(logCodeType, "出错了,代理公司id:" + agentId + "======="
				// + e);
			}
		}
		return list.size();
	}
}
